/*
Copyright (c) 2020-2022, Huawei Technologies Co., Ltd
 All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

* Description: 2D图表可视化插件数据界面类
*/
#ifndef CURVE_DISPLAY_H
#define CURVE_DISPLAY_H

#include <rviz/properties/enum_property.h>
#include <rviz/properties/int_property.h>
#include <rviz/properties/color_property.h>
#include <rviz/properties/float_property.h>

#include <qwt_plot_grid.h>
#include <qwt_plot_curve.h>

#include "curve/curve_data.h"
#include "curve/ui_curve_widget.h"
#include "common/chart_display_base.h"


namespace chart_plugin {
class CurveDisplay : public ChartDisplayBase<custom::PlotData> {
    Q_OBJECT

public:
    CurveDisplay() = default;
    ~CurveDisplay() override = default;

    /*
     * 功能：自定义插件的初始化函数，在Rviz对插件进行初始化时调用，继承自父类
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void onInitialize() override;

    /*
     * 功能：通知rviz Display清除其状态，同时这里也清除自己的topic数据，继承自父类并重写
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void reset() override;

public Q_SLOTS:
    /*
     * 功能：QwtPlot的标题控制槽，当标题控制属性内容被修改时，此槽会被调用以控制界面标题同步修改
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateChartTitle();

    /*
     * 功能：QwtPlot的X轴控制槽，当X轴控制属性内容被修改时，此槽会被调用以控制界面X轴名字同步变化
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateXAxisTitle();

    /*
     * 功能：QwtPlot的Y轴控制槽，当Y轴控制属性内容被修改时，此槽会被调用以控制界面Y轴名字同步变化
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateYAxisTitle();

    /*
     * 功能：更新曲线属性控制选项为用户所选择的曲线
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateCurveChoice();

    /*
     * 功能：更新曲线标题名字为用户更改的名字
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateCurveTitle();

    /*
     * 功能：更新曲线的颜色和透明度为用户修改的值
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateCurveColorAndAlpha();

protected:
    /*
     * 功能：插件激活时需要进行的操作，继承自父类
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void onEnable() override;

    /*
     * 功能：清除数据缓存，重新订阅topic，继承自父类
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void updateTopic() override;

    /*
     * 功能：当接收到topic数据时，由父类回调此接口，继承自父类
     * 输入参数：message-topic接收到的数据指针
     * 输出参数：无
     * 返回值：无
     */
    void ProcessMessage(const custom::PlotData::ConstPtr &message) override;

    /*
     * 功能：重写事件过滤器，这里捕获窗口大小变化事件
     * 输入参数：obj-QObject指针，e-QEvent *
     * 输出参数：无
     * 返回值：true-事件停止进一步处理，false-事件可被继续分发处理
     */
    bool eventFilter(QObject *obj, QEvent *e) override;

private:
    /*
     * 功能：清除topic接收到的缓存数据信息，重绘界面
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void Clear();

    /*
     * 功能：初始化标题属性控制元素
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void InitTitleProperty();

    /*
     * 功能：初始化第一条曲线属性控制元素
     * 输入参数：curveProperty-EnumProperty
     * 输出参数：无
     * 返回值：无
     */
    void InitFirstCurveProperty(rviz::EnumProperty &curveProperty);

    /*
     * 功能：初始化第二条曲线属性控制元素
     * 输入参数：curveProperty-EnumProperty
     * 输出参数：无
     * 返回值：无
     */
    void InitSecondCurveProperty(rviz::EnumProperty &curveProperty);

    /*
     * 功能：初始化插件的曲线属性控制元素
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void InitCurveProperty();

    /*
     * 功能：初始化插件的各个属性控制元素
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void InitProperty();

    /*
     * 功能：初始化QwtPlot上的元素和显示风格
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void InitQwtPlotStyle();

    /*
     * 功能：初始化曲线显示风格
     * 输入参数：titleProperty-标题属性，colorProperty-颜色属性，alphaProperty-透明度属性
     * 输出参数：curve-曲线
     * 返回值：无
     */
    void InitCurveStyle(QwtPlotCurve &curvePlot, rviz::StringProperty &titleProperty,
        const rviz::ColorProperty &colorProperty, const rviz::FloatProperty &alphaProperty);

    /*
     * 功能：根据输入参数font、字符串text和显示区域宽度displayAreaWidth值来处理字符串text为省略文本显示风格
     * 输入参数：font-字体，text-待处理字符串，displayAreaWidth-显示字符串区域宽度值
     * 输出参数：无
     * 返回值：text被处理后的值
     */
    const QString StringElidedText(const QFont &font, const QString &text, const int32_t displayAreaWidth);

    /*
     * 功能：控制当前曲线是否显示
     * 输入参数：item-当时被控制的曲线，isVisible-控制显隐
     * 输出参数：无
     * 返回值：无
     */
    void ShowCurve(QwtPlotItem *item, bool isVisible);

private:
    UiCurveWidget ui {};
    QWidget widget {};
    QwtPlotGrid grid {};
    QwtPlotCurve firstCurve {};
    QwtPlotCurve secondCurve {};
    QString squareDifference {};

    CurveData curveData {};
    rviz::StringProperty *qwtPlotTitleProperty { nullptr };
    rviz::StringProperty *xAxisTitleProperty { nullptr };
    rviz::StringProperty *yAxisTitleProperty { nullptr };

    rviz::EnumProperty *curveProperty { nullptr };
    rviz::StringProperty *firstCurveTitleProperty { nullptr };
    rviz::ColorProperty *firstCurveColorProperty { nullptr };
    rviz::FloatProperty *firstCurveAlphaProperty { nullptr };
    rviz::StringProperty *secondCurveTitleProperty { nullptr };
    rviz::ColorProperty *secondCurveColorProperty { nullptr };
    rviz::FloatProperty *secondCurveAlphaProperty { nullptr };
};
} // namespace chart_plugin

#endif // CURVE_DISPLAY_H
